﻿using System;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Rhino.Mocks;
using WroxGallery;
using WroxGallery.Controllers;
using WroxGallery.Models;
using WroxGallery.Models.Interfaces;

namespace WroxGallery.Tests.Controllers
{
    /// <summary>
    /// Summary description for HomeControllerTest
    /// </summary>
    [TestClass]
    public class HomeControllerTest
    {
        private MockRepository mocks;
        private IConfigurationRepository configurationRepository;
        private IGalleryRepository galleryRepository;

        [TestInitialize]
        public void SetupController()
        {
            mocks = new MockRepository();
            configurationRepository = mocks.DynamicMock<IConfigurationRepository>();
            galleryRepository = mocks.DynamicMock<IGalleryRepository>();

        }

        private PhotoCollection BuildFakePhotoList(int size)
        {
            PhotoCollection collection = new PhotoCollection();
            for (int i = 0; i < size; i++)
            {
                collection.Add(new Photo());
            }
            return collection;
        }


        private static PhotoCollection GetModel(ViewResult result)
        {
            Assert.IsNotNull(result, "Not a view result");
            return result.ViewData.Model as PhotoCollection;
        }

        [TestMethod]
        public void HomeController_HomePage_Contains_List_Of_Five_Images()
        {
            using (mocks.Record())
            {
                Expect.Call(galleryRepository.GetLatestPhoto(5)).Return(BuildFakePhotoList(5));
            }
            HomeController controller = new HomeController(configurationRepository, galleryRepository);

            using (mocks.Playback())
            {
                ViewResult result = controller.Index() as ViewResult;
                PhotoCollection model = GetModel(result);
                Assert.AreEqual(5, model.Count);
            }
        }

        [TestMethod]
        public void HomeController_About_Page_Displays_About_Description()
        {
            using (mocks.Record())
            {
                Expect.Call(configurationRepository.About).IgnoreArguments().Return("About");
            }

            HomeController controller = new HomeController(configurationRepository, galleryRepository);

            using (mocks.Playback())
            {
                ViewResult result = controller.About() as ViewResult;
                Assert.AreEqual("About", result.ViewData["AboutText"]);
            }
        }


        [TestMethod]
        public void HomeController_Album_Page_Contains_List_Of_Photos_From_Album()
        {
            using (mocks.Record())
            {
                Expect.Call(galleryRepository.GetPhotosInAlbum("12345",5)).Return(BuildFakePhotoList(5));
            }

            HomeController controller = new HomeController(configurationRepository, galleryRepository);

            using (mocks.Playback())
            {
                ViewResult result = controller.Album("12345","") as ViewResult;
                PhotoCollection model = GetModel(result);
                Assert.AreEqual(5, model.Count);
            }
        }

        [TestMethod]
        public void HomeController_Search_Redirects_To_Tag_Action()
        {
            HomeController controller = new HomeController(configurationRepository, galleryRepository);
            RedirectToRouteResult result = controller.Search("tag") as RedirectToRouteResult;
            Assert.IsNotNull(result, "Not a redirect result");
            Assert.AreEqual("Tag", result.RouteValues["Action"]);
            Assert.AreEqual("tag", result.RouteValues["Id"]);
        }

        [TestMethod]
        public void HomeController_Tag_Page_Contains_List_Of_Photos_Searched_By_Tag_Name()
        {
            using (mocks.Record())
            {
                Expect.Call(galleryRepository.SearchPhotosByTag("snow",5)).Return(BuildFakePhotoList(5));
            }

            HomeController controller = new HomeController(configurationRepository, galleryRepository);

            using (mocks.Playback())
            {
                ViewResult result = controller.Tag("snow") as ViewResult;
                PhotoCollection model = GetModel(result);
                Assert.AreEqual(5, model.Count);
            }
        }

        [TestMethod]
        public void HomeController_HomePage_Adds_Correct_AlbumName()
        {
            HomeController controller = new HomeController(configurationRepository, galleryRepository);

            ViewResult result = controller.Index() as ViewResult;
            Assert.AreEqual("Recent pics", result.ViewData["AlbumName"]);
        }

        [TestMethod]
        public void HomeController_Tag_Adds_Correct_AlbumName()
        {
            HomeController controller = new HomeController(configurationRepository, galleryRepository);

            ViewResult result = controller.Tag("Snow") as ViewResult;
            Assert.AreEqual("Search result: Snow", result.ViewData["AlbumName"]);
        }

        [TestMethod]
        public void HomeController_Album_Adds_Correct_AlbumName()
        {
            HomeController controller = new HomeController(configurationRepository, galleryRepository);

            ViewResult result = controller.Album("12345","Photo Album") as ViewResult;
            Assert.AreEqual("Album Photo Album", result.ViewData["AlbumName"]);
        }


        [TestMethod]
        public void HomeController_Album_Page_Renders_Index_View()
        {
            HomeController controller = new HomeController(configurationRepository, galleryRepository);

            ViewResult result = controller.Album("12345","") as ViewResult;
            Assert.AreEqual("Index", result.ViewName);
        }

        [TestMethod]
        public void HomeController_Tag_Page_Renders_Index_View()
        {
            HomeController controller = new HomeController(configurationRepository, galleryRepository);

            ViewResult result = controller.Tag("snow") as ViewResult;
            Assert.AreEqual("Index", result.ViewName);
        }


        [TestMethod]
        public void HomeController_Tags_Action_Returns_Plain_List_Of_Tags()
        {
            using (mocks.Record())
            {
                Expect.Call(galleryRepository.TagList("Ta")).Return(BuildTagList());
            }

            HomeController controller = new HomeController(configurationRepository, galleryRepository);

            using (mocks.Playback())
            {
                ContentResult result = controller.Tags("Ta") as ContentResult;
                Assert.IsNotNull(result, "Not a view result");
                Assert.AreEqual("Tag_1\r\nTag_2", result.Content);
            }
        }

        private StringCollection BuildTagList()
        {
            StringCollection collection = new StringCollection();
            for (int i = 1; i <= 2; i++)
            {
                collection.Add("Tag_"+i);
            }
            return collection;
        }
    }
}
